package cn.boysoft.core.manager.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;

import org.apache.commons.lang.StringUtils;
import javax.persistence.Query;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.boysoft.core.Constants;
import cn.boysoft.core.annotation.JEEService;
import cn.boysoft.core.manager.Manager;
import cn.boysoft.core.model.JEEQuery;
import cn.boysoft.core.model.Page;
import cn.boysoft.core.model.PageParam;
import cn.boysoft.core.model.QueryCondition;

/**
 * 
 * @author 付厚俊
 * CreateTime 2013-4-4 下午5:09:32
 */
@Service(value="manager")
@Transactional
public class ManagerImpl<T,P extends PageParam>    implements Manager<T,P>{
	protected Class<T> entityClazz;
	public ManagerImpl(){
		this.entityClazz = this.getEntityClazz();
	}
	@PersistenceContext
    protected	EntityManager em;// 注入实体管理器
	
	@Override
	@Transactional
	@JEEService(commandId=Constants.COMMAND_SAVE,name="保存",needValue=false)
	public T save(T t) {
		em.persist(t);
		return t;
	}

	@Override
	@Transactional
	@JEEService(commandId=Constants.COMMAND_UPDATE,name="修改",needValue=false)
	public T update(T t) {
		em.merge(t);
		return t;
	}

	@Override
	@Transactional
	@JEEService(commandId=Constants.COMMAND_DELETE,name="删除",needValue=false)
	public void delete(Serializable... ids) {
		if (ids != null) {
			for (Serializable id : ids) {
				T entity = em.getReference(entityClazz, id);
				if (entity != null) {
					em.remove(entity);
				}
			}
		}
	}
	@Override
	@JEEService(commandId=Constants.COMMAND_GET,name="获取")
	public T get(Serializable id) {
		return em.find(entityClazz, id);
	}
	public Object get(Class clazz,Serializable id) {
		return em.find(clazz, id);
	}
	@JEEService(commandId=Constants.COMMAND_FIND,name="查询")
	@Override
	public Page<T> queryPage(P pageParam) {
		if(pageParam instanceof JEEQuery){
			JEEQuery query = (JEEQuery)pageParam;
			QueryCondition queryCondition = query.buildQueryCondition();
			if(queryCondition != null){
				return this.queryPage(queryCondition.getHql().toString(), 
						pageParam.getFirst(), 
						pageParam.getPageSize(), 
						queryCondition.getValues());
			}
		}
		
		String hql = " from  "+this.getEntityClazz().getName();
		return this.queryPage(hql, 
				pageParam.getFirst(), 
				pageParam.getPageSize(), 
				null);
	}    
	@SuppressWarnings("unchecked")
	@Override
	public List<T> queryList(String hql, List<Object> values) {
		Query query = em.createQuery(hql);
		setParameter(query, values);
		List<T> list = query.getResultList();
		return list;
	}
	public List<T> queryAll(String hql) {
		Query query = em.createQuery(hql);
		List<T> list = query.getResultList();
		return list;
	}
	@SuppressWarnings("unchecked")
	@Override
	public T queryUnique(String hql, List<Object> values) {
		Query query = em.createQuery(hql);
		setParameter(query, values);
		T result = null;
		try{
			result = (T) query.getSingleResult();
		}catch(NoResultException e){
			
		}
		return result;
	}
	public Object getSingleResult(String hql, List<Object> values) {
		Query query = em.createQuery(hql);
		setParameter(query, values);
		Object result = null;
		try{
			result = query.getSingleResult();
		}catch(NoResultException e){
		}
		return result;
	}
	@SuppressWarnings("unchecked")
	@Override
	public Page<T> queryPage(String hql, int start, int pageSize,
			List<Object> values) {
		Page<T> page = new Page<T>();
		String countHql = getCountHql(hql);
		Query query = em.createQuery(countHql);
		setParameter(query, values);
		Object count = query.getSingleResult();
		Long total = (Long) count;
		if (total > 0) {
			page.setTotal(total);
			query = em.createQuery(hql);
			query.setFirstResult(start - 1);
			query.setMaxResults(pageSize);
			setParameter(query, values);
			List<T> list = query.getResultList();
			page.setRows(list);
		}
		return page;
	}

	
	@SuppressWarnings("unchecked")
	public Class<T> getEntityClazz() {
		Type type = this.getClass().getGenericSuperclass();
		if (type instanceof ParameterizedType) {
			ParameterizedType parameterizedType = (ParameterizedType) type;
			return (Class) parameterizedType.getActualTypeArguments()[0];
		}
		return null;
	}
	@SuppressWarnings("unchecked")
	public Class<T> getPageParamClazz() {
		Type type = this.getClass().getGenericSuperclass();
		if (type instanceof ParameterizedType) {
			ParameterizedType parameterizedType = (ParameterizedType) type;
			return (Class) parameterizedType.getActualTypeArguments()[1];
		}
		return null;
	}
	public static void setParameter(Query query, List<Object> values) {
		if (values != null) {
			for (int i = 0; i < values.size(); i++) {
				query.setParameter(i + 1, values.get(i));
			}
		}
	}

	protected String getCountHql(String hql) {
		String countHql = "from " + StringUtils.substringAfter(hql, "from");
		countHql = "select count(*) " + countHql;
		return countHql;
	}
}
